#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#include <string>
#include <vector>

#include "Backdoor.h"

#pragma warning(disable:4996)

class ChatBot
{
public:
	ChatBot(bool isServer)
	{
		mCommandIndex = 0;
		if ( isServer )
		{
			mFph = fopen("BackdoorServer.txt", "wb");
			mBackdoor = createBackdoor("BACKDOOR_SERVER","BACKDOOR_CLIENT");
			printf("Starting Chat as the Server\r\n");
		}
		else
		{
			mFph = fopen("BackdoorClient.txt", "wb");
			mBackdoor = createBackdoor("BACKDOOR_CLIENT","BACKDOOR_SERVER");
			printf("Starting Chat as the Client\r\n");
		}
	}
	virtual ~ChatBot(void)
	{
		if ( mBackdoor )
		{
			mBackdoor->release();
		}
		if ( mFph )
		{
			fclose(mFph);
		}
	}

	bool process(void)
	{
		bool ret= false;
		char buf[256];
		bool exit = getInputString(buf,256);
		if ( !exit )
		{
			if ( mBackdoor )
			{
				mBackdoor->send("%s",buf);
			}
			printf("Sending: %s\r\n", buf );
			ret = true; // keep processing...
		}
		return ret;
	}

	bool getInputString(char *buf,int len)
	{
		bool ret = false;
		int index = 0;
		bool exit = false;

		while ( !exit )
		{
			if ( mBackdoor )
			{
				int argc;
				const char **argv = mBackdoor->getInput(argc);
				if ( argv )
				{
					printf("Received:");
					for (int i=0; i<argc; i++)
					{
						printf("%s ", argv[i] );
					}
					printf("\r\n");
					if ( mFph )
					{
						fprintf(mFph,"Received:");
						for (int i=0; i<argc; i++)
						{
							fprintf(mFph,"%s ", argv[i] );
						}
						fprintf(mFph,"\r\n");
						fflush(mFph);
					}
				}
			}


			if ( _kbhit() )
			{
				int c = (int)_getch();
				if ( c == 224 )
				{
					c = 256+(int)_getch();
				}

				if ( c == 10 || c == 13 )
				{
					buf[index] = 0;
					pushString(buf);
					exit = true;
				}
				else if ( c == 336 ) // Down-Arrow
				{
					mCommandIndex++;
					if ( mCommandIndex < mCommands.size() )
					{
						for (int i=0; i<index; i++)
						{
							printf("%c",8);
							printf(" ");
							printf("%c",8);
						}
						const char *cmd = mCommands[mCommandIndex].c_str();
						strcpy(buf,cmd);
						index = strlen(buf);
						printf("%s", buf );
					}
					else
					{
						mCommandIndex = mCommands.size();
					}
				}
				else if ( c == 328 ) // Up-Arrow
				{
					if ( mCommandIndex > 0 )
					{
						mCommandIndex--;
						for (int i=0; i<index; i++)
						{
							printf("%c",8);
							printf(" ");
							printf("%c",8);
						}
						const char *cmd = mCommands[mCommandIndex].c_str();
						strcpy(buf,cmd);
						index = strlen(buf);
						printf("%s", buf );
					}
				}
				else if ( c == 27 )
				{
					buf[index] = 0;
					exit = true;
					ret = true;
				}
				else if ( c == 8 )
				{
					if ( index )
					{
						index--;
						printf("%c",c);
						printf(" ");
						printf("%c",c);
					}
				}
				else 
				{
					if ( c >= 32 && c <= 127 )
					{
						buf[index] = c;
						index++;
						printf("%c",c);
						if ( index == (len-1) )
							break;
					}
				}
			}
		}

		buf[index] = 0;

		printf("\n");

		return ret;
	}

	void pushString(const char *str)
	{
		std::string s = str;
		mCommands.push_back(s);
		mCommandIndex = mCommands.size();
	}


private:
	FILE					*mFph;
	size_t						mCommandIndex;
	std::vector< std::string > mCommands;
	Backdoor	*mBackdoor;
};

void main(int argc,const char **argv)
{
	if ( argc == 1 )
	{
		printf("Usage: Backdoor <client/server>\r\n");
	}
	else
	{
		bool server = true;
		if ( strcmp(argv[1],"client") == 0 )
		{
			server = false;
		}
		ChatBot bot(server);
		while ( bot.process() );
	}
}
